import {Injectable} from '@angular/core';
import {AlertController, Platform} from "ionic-angular";
import {CallNumber} from "@ionic-native/call-number";
import {DialogProvider} from "@providers/dialog";
import {AppVersion} from "@ionic-native/app-version";
import {Observable} from "rxjs/Observable";
import {HttpClient} from '@angular/common/http';
import {HttpProvider} from "@providers/http";
import {WechatJsSdkProvider} from "@providers/wechat-js-sdk";
import {ForkJoinObservable} from "rxjs/observable/ForkJoinObservable";
import {File, FileEntry} from "@ionic-native/file";
import {BarcodeScanner, BarcodeScannerOptions} from "@ionic-native/barcode-scanner";
import {ImagePicker} from "@ionic-native/image-picker";
import {Camera, CameraOptions} from "@ionic-native/camera";
import {FileObj} from "@common/FileObj";
import {PhotoViewer} from "@ionic-native/photo-viewer";
import {env} from "@env/environment";
import QRCode from 'qrcode'
import {ImageViewerController} from 'ionic-img-viewer';


/*
  Generated class for the NativeProvider provider.

  See https://angular.io/guide/dependency-injection for more info on providers
  and Angular DI.
*/
@Injectable()
export class NativeProvider {

  isCordova: boolean = false;

  constructor(private platform: Platform,
              private callNumber: CallNumber,
              private dialog: DialogProvider,
              private file: File,
              private photoViewer: PhotoViewer,
              private imagePicker: ImagePicker,
              private camera: Camera,
              private alertCrtl: AlertController,
              private barcodeScanner: BarcodeScanner,
              private http: HttpClient,
              private http2: HttpProvider,
              private imageViewerCtrl: ImageViewerController,
              private wechat: WechatJsSdkProvider,
              private appVersion: AppVersion) {
    this.platform.ready().then(() => {
      this.isCordova = this.platform.is("cordova")
    })
  }

  /**
   * 打电话
   * @param tel
   * @returns {Promise<any>}
   */
  call(tel): Promise<any> {
    return new Promise<any>((resolve) => {
      if (this.isCordova) {
        this.callNumber.callNumber(tel, true)
          .then(resolve)
      } else {
        let a = document.createElement("a");
        a.href = "tel:" + tel;
        a.click();
        resolve();
      }
    })
  }

  /**
   * 根据经纬度计算两点距离
   * @return number
   */
  getGreatCircleDistance(lng1, lat1, lng2, lat2): number {
    let getRad = (d: number): number => {
      let PI = Math.PI;
      return d * PI / 180.0;
    };

    let EARTH_RADIUS = 6378137.0; //单位M
    let radLat1 = getRad(lat1);
    let radLat2 = getRad(lat2);

    let a = radLat1 - radLat2;
    let b = getRad(lng1) - getRad(lng2);

    let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
    s = s * EARTH_RADIUS;
    s = Math.round(s * 10000) / 10000.0;

    return s;
  }

  /**
   * 是否真机环境
   */
  isMobile(): boolean {
    return this.platform.is('cordova');
  }


  /*/!**
   * 检查版本更新
   * @param isToast  当app已经是最新版本时是否弹出提示是最新版本,默认不提示
   *!/
  public checkVersion(isToast?: boolean) {
    if (!this.isMobile) {
      this.dialog.showAlert("浏览器访问此功能无效");
      return;
    }
    let configXml = env.APP_UPDATE_XML;
    if (Util.isNull(configXml)) return;
    this.appUpdate.checkAppUpdate(configXml);
    /!*.then((code) => {
        /!**
         * 对比版本号
         *!/
        let VERSION_NEED_UPDATE = 201; //检查到需要更新； need update
        let VERSION_UP_TO_UPDATE = 202; //软件是不需要更新；version up to date
        let VERSION_UPDATING = 203; //软件正在更新；version is updating

        /!**
         * 版本解析错误
         *!/
        let VERSION_RESOLVE_FAIL = 301; //版本文件解析错误 version-xml file resolve fail
        let VERSION_COMPARE_FAIL = 302; //版本文件对比错误 version-xml file compare fail

        /!**
         * 网络错误
         *!/
        let REMOTE_FILE_NOT_FOUND = 404;
        let NETWORK_ERROR = 405;

        /!**
         * 没有相应的方法
         *!/
        let NO_SUCH_METHOD = 501;

        /!**
         * Permissions没有权限
         *!/
        let PERMISSION_DENIED = 601;

        /!**
         * 未知错误
         *!/
        let UNKNOWN_ERROR = 901;

        switch (code) {
          case VERSION_NEED_UPDATE://检查到需要更新； need update
            this.dialog.showToast('检查到需要更新');
            break;
          case VERSION_UP_TO_UPDATE : //软件是不需要更新；version up to date
            this.dialog.showToast('已经是最新版本');
            break;
          case VERSION_UPDATING : //软件正在更新；version is updating
            this.dialog.showToast('正在更新请稍候');
            break;
          case VERSION_RESOLVE_FAIL : //版本文件解析错误 version-xml file resolve fail
            this.dialog.showToast('版本文件解析错误');
            break;
          case VERSION_COMPARE_FAIL : //版本文件对比错误 version-xml file compare fail
            this.dialog.showToast('版本文件对比错误');
            break;
          case REMOTE_FILE_NOT_FOUND :
          case NETWORK_ERROR :
            this.dialog.showToast('网络错误');
            break;
          case NO_SUCH_METHOD :
            this.dialog.showToast('服务器异常');
            break;
          case PERMISSION_DENIED :
            this.dialog.showToast('没有存储权限');
            break;
          case UNKNOWN_ERROR :
            this.dialog.showToast('未知错误');
            break;
        }
      }
    );*!/
  }*/


  /**
   * 是否android真机环境
   */
  isAndroid(): boolean {
    return this.isMobile() && this.platform.is('android');
  }

  /**
   * 是否ios真机环境
   */
  isIos(): boolean {
    return this.isMobile() && (this.platform.is('ios') || this.platform.is('ipad') || this.platform.is('iphone'));
  }

  //获取安装包版本号
  getVersionNumber() {
    return this.appVersion.getVersionNumber();
  }

  /**
   * 图片上传-上传到文件服务器
   * @param localIds：picList
   */
  uploadImageFile(localIds: any[]): Observable<any> {
    return Observable.create((observer) => {
      if (this.wechat.isWechat()) {
        this.wechat.uploadImage(localIds).then(v => {
          this.http.post("/trust/weixin/wxUploadImg.do", {
            json: v['s'],
            appid: this.wechat.appid
          }).subscribe(fileList => {
            console.log(fileList)
            /* let fileUrlArr: any[] = []; //存储图片路径
             for (let i = 0; i < fileList.length; i++) {
               fileUrlArr.push(fileList[i].FILE_URL);
             }
             observer.next([...v['f'], ...fileUrlArr]);*/
          }, error => {
            observer.next(error);
          });
        })
      } else {
        let serverIdArr: any[] = [];
        localIds.forEach(value => {
          serverIdArr.push(value["origPath"]);
        });
        let formData = new FormData();
        this.upload(serverIdArr, formData).subscribe(data => {
          this.http.post(env.app_serve_url + "/FormUpload/multiUpload.do", formData).subscribe(message => {
            let fileUrlArr: any[] = [];
            let fileList = message["data"]["resultData"];
            fileList.forEach(value => {
              fileUrlArr.push(value.FILE_URL);
            });
            observer.next(fileUrlArr);
            observer.complete();
          }, error => {
            console.info(error);
            observer.error(error);
          });
        });
      }
    });
  }

  /**
   * 文件批量上传调用方法，
   * @param filePaths  文件本地的绝对路径，该参数是个数组
   * @param formData  返回的FormData类型的键值对，可直接作为参数调用http请求
   * @returns {Observable<T[]>}
   */
  upload(filePaths: Array<string>, formData: FormData): Observable<any> {
    //每个文件上传任务创建一个信号
    let observables: Array<any> = [];
    filePaths.forEach((value: string, i, array) => {
      if (!value.startsWith('file://')) {
        value = 'file://' + value;
      }
      let observable = new Observable((sub: any) => {
        this.file.resolveLocalFilesystemUrl(value).then(entry => {
          (<FileEntry>entry).file(file => {
            // this.readFile(<Blob>file);
            let blob: Blob = <Blob>file;
            const reader = new FileReader();
            reader.onloadend = () => {
              const imgBlob = new Blob([reader.result], {type: blob.type});
              formData.append('file', imgBlob, (<any>blob).name);
              sub.next(null);
              sub.complete();
            };
            reader.readAsArrayBuffer(blob);
          });
        }).catch(error => {
          sub.error(error);
          console.log('报错了，日了狗----->' + JSON.stringify(error));
        });
      });
      observables.push(observable);
    });
    return ForkJoinObservable.create(observables);
  }

  openScanner(barcodeScannerOptions?: BarcodeScannerOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      if (this.isCordova) {
        let options: BarcodeScannerOptions = Object.assign({
          showTorchButton: false//开启手电筒
        }, barcodeScannerOptions);
        this.barcodeScanner.scan(options).then(res => {
          resolve(res.text);
        }).catch(err => {
          reject(err);
        })
      } else if (this.wechat.isWechat()) {
        return this.wechat.scanQRCode()
      } else {
        let alert = this.alertCrtl.create({
          message: "输入条码",
          inputs: [{type: 'string', name: 'code'}],
          buttons: [{
            text: "取消",
            role: 'cancel',
            handler: () => {
              // resolve('');
            }
          }, {
            text: "确定",
            handler: (res) => {
              let code = res.code;
              resolve(code);
            }
          }]
        });
        alert.present();
      }
    });
  }

  imagedowablelode(ID?: any): Promise<any> {
    return new Observable((observer) => {
      this.http2.post("/Inbound/invoke.do", {
        interfaceId: 'csm.distributor.selectfptp',
        data: JSON.stringify({
          ID: ID
        })
      }).subscribe(data => {
        let datas: any[] = data['data'];
        let files: FileObj[] = [];
        for (let i = 0; i < datas.length; i++) {
          let file = new FileObj();
          file.origPath = env.app_serve_url + '/FormUpload/download.do?url=' + datas[i]['PICTURE'] + '&filename=a.jpg';
          file.thumbPath = env.app_serve_url + '/FormUpload/download.do?url=' + datas[i]['PICTURE'] + '&filename=a.jpg';
          file.id = datas[i]['XLH'];
          files.push(file);
        }
        observer.next(files);
        observer.complete();
      }, error => {
        observer.error(error);
      })
    }).toPromise();
  }

  delImage(event): Promise<any> {
    return new Observable((observer) => {
      this.http2.post("/Inbound/invoke.do", {
        interfaceId: 'csm.distributor.deletefptp',
        data: JSON.stringify({
          XLH: event.id
        })
      }).subscribe(data => {
        observer.next(data);
        observer.complete();
      }, error => {
        observer.error(error);
      });
    }).toPromise();
  }

  imageUpload(event, ID?: any): Promise<any> {
    return new Observable((observer) => {
      let list: any[] = [];
      list.push(event);
      this.uploadImageFile(list).subscribe(res => {
        this.http2.post("/Inbound/invoke.do", {
          interfaceId: 'csm.distributor.insertfptp',
          data: JSON.stringify({
            ID: ID,
            PICTURE: res[0]
          })
        }).subscribe(data => {
          event.id = data;
          event.origPath = res[0];
          event.thumbPath = res[0];
          observer.next(event);
          observer.complete();
        }, error => {
          observer.error(error);
          //this.dialog.showAlert("error:" + JSON.stringify(error));
        });
      });
    }).toPromise();
  }

  /**
   * 通过拍照获取照片
   * @param options
   */
  getPictureByCamera(options: CameraOptions = {}): Observable<string> {
    let ops: CameraOptions = Object.assign({
      sourceType: this.camera.PictureSourceType.CAMERA,
      destinationType: this.camera.DestinationType.DATA_URL//DATA_URL: 0 base64字符串, FILE_URI: 1图片路径
    }, options);
    return this.getPicture(ops);
  };

  /**
   * 使用cordova-plugin-camera获取照片
   *  ionic cordova plugin add cordova-plugin-camera
   *  npm install --save @ionic-native/camera
   * @param options
   */
  getPicture(options: CameraOptions = {}): Observable<string> {
    let ops: CameraOptions = Object.assign({
      sourceType: this.camera.PictureSourceType.CAMERA,//图片来源,CAMERA:拍照,PHOTOLIBRARY:相册
      destinationType: this.camera.DestinationType.DATA_URL,//默认返回base64字符串,DATA_URL:base64   FILE_URI:图片路径
      quality: 50,//图像质量，范围为0 - 100
      allowEdit: false,//选择图片前是否允许编辑
      encodingType: this.camera.EncodingType.JPEG,
      //saveToPhotoAlbum: true,//是否保存到相册
      correctOrientation: true//设置摄像机拍摄的图像是否为正确的方向
    }, options);
    return Observable.create(observer => {
      this.camera.getPicture(ops).then((imgData: string) => {
        if (ops.destinationType === this.camera.DestinationType.DATA_URL) {
          observer.next('data:image/jpg;base64,' + imgData);
        } else {
          observer.next(imgData);
        }
        observer.complete();
      }).catch(err => {
        if (err == 20) {
          this.dialog.showAlert('没有权限,请在设置中开启权限');
          return;
        }
        if (String(err).indexOf('cancel') != -1) {
          return;
        }
        console.log('使用cordova-plugin-camera获取照片失败');
        this.dialog.showAlert(err);
        this.dialog.showAlert('获取照片失败');
      });
    });
  };

  /**
   * 通过图库选择多图
   * ionic cordova plugin add cordova-plugin-telerik-imagepicker --variable PHOTO_LIBRARY_USAGE_DESCRIPTION="your usage message"
   * npm install --save @ionic-native/image-picker
   * @param options
   */
  getMultiplePicture(options = {}): Observable<any> {
    let that = this;
    let ops = Object.assign({
      maximumImagesCount: 6,
      width: 800,//缩放图像的宽度（像素）
      height: 800,//缩放图像的高度（像素）
      quality: 50//图像质量，范围为0 - 100
    }, options);
    return Observable.create(observer => {
      this.imagePicker.getPictures(ops).then(files => {
        let destinationType = options['destinationType'] || 1;//0:base64字符串,1:图片url
        if (destinationType === 1) {
          observer.next(files);
        } else {
          let imgBase64s = [];//base64字符串数组
          for (let fileUrl of files) {
            that.convertImgToBase64(fileUrl).subscribe(base64 => {
              imgBase64s.push(base64);
              if (imgBase64s.length === files.length) {
                observer.next(imgBase64s);
              }
            })
          }
        }
      }).catch(err => {
        observer.error(err);
      });
    });
  };

  /**
   * 根据图片绝对路径转化为base64字符串
   * 注意：base64字符串上传到后台时，系统会自动把“+”号转换成空格，
   * 若要对base64解密，请先把空格转换回“+”号
   *  ionic cordova plugin add cordova-plugin-file
   *  npm install --save @ionic-native/file
   * @param path 绝对路径
   */
  convertImgToBase64(path: string): Observable<string> {
    if (!path.startsWith('file://')) {
      path = 'file://' + path;
    }
    return Observable.create(observer => {
      this.file.resolveLocalFilesystemUrl(path).then((fileEnter: FileEntry) => {
        fileEnter.file(file => {
          let reader = new FileReader();
          reader.onloadend = function (e) {
            observer.next(this.result);
            observer.complete();
          };
          reader.readAsDataURL(file);
        });
      }).catch(err => {
        observer.error(err);
        console.log('根据图片绝对路径转化为base64字符串失败');
      });
    });
  }

  /**
   * 点击图片放大显示预览
   * ionic cordova plugin add com-sarriaroman-photoviewer
   * npm install --save @ionic-native/photo-viewer
   */
  previewImage(url: string) {
    this.photoViewer.show(url);
  }

  /**
   * 二维码
   * @param content
   */
  getQrCode(content): Promise<string> {
    return new Promise(resolve => {
      QRCode.toDataURL(content)
        .then(url => {
          resolve(url)
        })
    })
  }

  viewImg(element) {
    const imageViewer = this.imageViewerCtrl.create(element);
    imageViewer.present();
  }
}
